package com.example.app.manager.c2;

import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.RequiresApi;
import android.util.Size;
import android.view.Surface;

import com.example.app.activity.MLog;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Comparator;

//拍照片
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
class CameraTakePhoto {
    private String tag = "CameraTakePhoto";
    private String imagePath;
    private ImageReader imageReader;
    private Handler backgroundHandler;


    public CameraTakePhoto setBackgroundHandler(Handler backgroundHandler) {
        this.backgroundHandler = backgroundHandler;
        return this;
    }


    private Size photoSize;

    public CameraTakePhoto setPhotSize(CameraCharacteristics characteristics, Size previewSize) {
        StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
        //获取图片输出的尺寸
        Size[] imageSize = map.getOutputSizes(ImageFormat.JPEG);

        //获取相机支持的最大拍照尺寸
        //photoSize = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
        //        new CompareSizesByArea());
        photoSize = selectPhotoSize(imageSize, previewSize);
        return this;
    }

    //获取合适的照片大小
    private Size selectPhotoSize(Size[] choices, Size previewSize) {
        int photoW = previewSize.getWidth();
        int photoH = previewSize.getHeight();
        Size photoSize = null;
        int px = photoW * photoH;
        double minVideo = Math.min(photoW, photoH);
        double maxVideo = Math.max(photoW, photoH);
        double fixationD = minVideo / maxVideo;
        double difference = -1;
        for (Size size : choices) {
            int w = size.getWidth();
            int h = size.getHeight();
            double min = Math.min(w, h);
            double max = Math.max(w, h);
            double d = min / max;
            MLog.e(tag, "照片大小列表 Width：" + w + " Height:" + h + " d:" + d);
            if (photoSize == null) {
                photoSize = size;
                difference = d;
                continue;
            }
            max = Math.max(fixationD, d);
            min = Math.min(fixationD, d);
            double f = min / max;
            if (f == 1 && difference != 1) {
                photoSize = size;
                difference = 1;
                continue;
            }
            int s = photoSize.getHeight() * photoSize.getWidth();
            if (f == 1 && difference == 1) {
                if (px == (w * h)) {
                    photoSize = size;
                    difference = 1;
                    break;
                }
                if (s < (photoW * photoH)) {
                    photoSize = size;
                    difference = 1;
                }
                continue;
            }
            f = Math.abs(f - d);
            if (difference < 1 && difference > f) {
                photoSize = size;
                difference = f;
                continue;
            }
            if (difference < 1 && difference == f && s < (w * h)) {
                photoSize = size;
                difference = f;
                continue;
            }

        }
        MLog.e(tag, "合适的照片大小 Width：" + photoSize.getWidth() + " Height:" + photoSize.getHeight());
        return photoSize;
    }

    public CameraTakePhoto setImageReader() {
        ///前三个参数分别是需要的尺寸和格式，
        // 最后一个参数代表每次最多获取几帧数据， 2代表ImageReader中最多可以获取两帧图像流
        imageReader = ImageReader.newInstance(photoSize.getWidth(), photoSize.getHeight(),
                ImageFormat.JPEG, 2);
        imageReader.setOnImageAvailableListener(new OnImageAvailable(),
                backgroundHandler);
        return this;
    }

    //获取拍照的Surface
    public Surface getImageReaderSurface() {
        return imageReader.getSurface();
    }

    //设置路径
    public void setImagePath(String imagePath) {
        this.imagePath = imagePath;
    }

    public void onClose() {
        if (imageReader == null) {
            return;
        }
        imageReader.close();
    }

    //拍照
    public void onTakePhoto(CameraDevice device, boolean isBack, Rect zoom,
                            CameraCaptureSession session,
                            CameraCaptureSession.CaptureCallback captureBack) throws CameraAccessException {
        CaptureRequest.Builder builder = device.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        builder.addTarget(imageReader.getSurface());
        //isCameraFront是自定义的一个boolean值，用来判断是不是前置摄像头，
        // 是的话需要旋转180°，不然拍出来的照片会歪了
        if (isBack) {
            builder.set(CaptureRequest.JPEG_ORIENTATION, 270);
        } else {
            builder.set(CaptureRequest.JPEG_ORIENTATION, 90);
        }
        //锁定焦点
        builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
        //判断预览的时候是否两指缩放过,是的话需要保持当前的缩放比例
        if (zoom != null) {
            builder.set(CaptureRequest.SCALER_CROP_REGION, zoom);
        }
        //停止预览
        session.stopRepeating();
        //咔擦拍照
        session.capture(builder.build(), captureBack, backgroundHandler);
    }

    //拍照回调
    class OnImageAvailable implements ImageReader.OnImageAvailableListener {

        @Override
        public void onImageAvailable(ImageReader reader) {
            //拍照动作
            MLog.e(tag, "拍照：path " + imagePath);
            Image image = reader.acquireNextImage();
            if (backgroundHandler == null) {
                onImageSave(image);
                return;
            }
            backgroundHandler.post(new ImageSave(image));
        }
    }

    private void onImageSave(Image image) {
        ByteBuffer buffer = image.getPlanes()[0].getBuffer();
        byte[] data = new byte[buffer.remaining()];
        buffer.get(data);
        Message msg = new Message();
        msg.obj = imagePath;
        try {
            FileOutputStream fos = new FileOutputStream(imagePath);
            fos.write(data, 0, data.length);
            fos.close();
            //
            msg.what = 20;

        } catch (IOException e) {
            e.printStackTrace();
            msg.what = 21;
         }
        image.close();
        if(backgroundHandler==null){
            MLog.e(tag, "拍照结束 但是不发送消息");
            return;
        }
        backgroundHandler.sendMessage(msg);
        MLog.e(tag, "拍照结束");
    }

    class ImageSave implements Runnable {
        private Image image;

        public ImageSave(Image image) {
            this.image = image;
        }

        @Override
        public void run() {
            onImageSave(image);
        }
    }

    class CompareSizesByArea implements Comparator<Size> {
        @Override
        public int compare(Size lhs, Size rhs) {
            return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
                    (long) rhs.getWidth() * rhs.getHeight());
        }

    }
}
